/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main;
import java.io.*;
/**
 *
 * @author Mantas, Ramūnas, Vilius
 */
public class Parser {
    public final static int MAX_STRING = 10;
    public static String startIP;
    public static String outputScreen = "";
    private static int outputRowCount=0;
    private static int outputCellCount=0;
    public static boolean pushed=false;

    public static void runProgram(){
        String command;
        PagingMechanism.convertVirtualIPToReal();
        
        while(Processor.getPI() != 3)//HALT
        {
            command = getCommand(Processor.getIP());
            executeCommand(command);
            
            if(Processor.getMODE() == 1)
                if(Processor.getSI() == 1) { //ERROR 
                        Processor.setInOut("ERROR: " + Processor.getIP());
                } else if(Processor.getSI() == 2) { //OVERFLOW
                        Processor.setInOut("OVERFLOW: " + Processor.getIP());
                } else if(Processor.getSI() == 3) { //BAD ASSIGN
                        Processor.setInOut("BAD ASSIGN: " + Processor.getIP());
                } else if(Processor.getPI() == 1) { //PRNT
                        int[] arg1 = dividePointer(Stack.getSP());
                        Processor.setInOut(Stack.getMemoryFrom(arg1[0], arg1[1]));
                        Processor.setTIMER(Processor.getTIMER()+2);
                } else if(Processor.getPI() == 2) { //SCAN
                        
                        Processor.setTIMER(Processor.getTIMER()+2);
                } 
                if(Processor.getStep() == 1) {
                //Processor.setSI(0);
                //Processor.setPI(0);
                break;
            }

            if(Processor.getTIMER() == 0) { //TIME IS UP
                //set to next program
                //break;
            }
            
            VirtualMachine.increaseIP();
            PagingMechanism.convertVirtualIPToReal();
            
        }
  
    }
    public static String getCommand(String ip){
        Integer row = Integer.parseInt(ip.substring(0, 2));
        Integer column = Integer.parseInt(ip.substring(2, 4));
        return Memory.getMemoryFrom(row, column);
    }

    public static void readFromFile() {
        try {
            FileInputStream fstream = new FileInputStream(System.getProperty("user.dir")+"/src/programa.txt");
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            Integer temp;
            Integer code = 0;
            Integer row = 0;
            Integer column = 0;
            Integer rowFromTable;
            Processor.setMODE(0);
            Processor.setSI(0);
            Processor.setPI(0);
            Processor.clearInOut();
            pushed = false;
            PagingMechanism.findBlockForPagingTable();
            PagingMechanism.findBlockForPagingTableStack(); 
            
            Integer PTR = Processor.getPTR();
            Integer SPTR = Processor.getSPTR();
            
            PagingMechanism.setPagingTableStack(row);
           
            Stack.setSP("0000");
            PagingMechanism.convertVirtualSPToReal();

            PagingMechanism.setPagingTable(row);
            
            VirtualMachine.setIP("0000");
            PagingMechanism.convertVirtualIPToReal();
           
            strLine = br.readLine();
            boolean pushFound = false;
            if (strLine.equals("$STR")) {
                while ((strLine = br.readLine()) != null &&
                        !strLine.equals("$END")){
                    
                    if (column > 15) {
                        column = 0;
                        row++;
                        PagingMechanism.setPagingTable(row);
                    }
                    
                   if(validateCommand(strLine) || pushFound){
                        temp = PagingMechanism.getPagingTableRow(row);
                        Memory.setMemoryAt(temp, column, strLine);
                        column++;
                        if(strLine.equals("PUSH")){
                            pushFound=true;
                        }else{
                            pushFound=false;
                        }                        
                    }
                    else 
                    { 
                        Processor.setMODE(1);
			Processor.setSI(1);
                        Processor.setPI(3);
                        
                        break;
                    }
            
                }
                in.close();
                PagingMechanism.convertVirtualSPToReal();
            }
            else
            {
                Processor.setMODE(1);
                Processor.setSI(1);
            }
            
        }
        catch (Exception e) {
            System.err.println("Nepavyko nuskaityti: " + e.getMessage());
        }
    }
    
    public static boolean validateCommand(String command){
       if(command.equals("ADD_") || command.equals("SUB_") ||
          command.equals("MUL_") || command.equals("DIV_") ||
          command.equals("CMP_") || command.equals("SCAN") ||
          command.equals("PRNT") || command.equals("PUSH") ||
          command.equals("POP_") || command.equals("BRN_") || 
               command.equals("HALT")){
           return true;
       }else if(command.startsWith("JM") || command.startsWith("JB") ||
                command.startsWith("JE") || command.startsWith("JA") ||
                command.startsWith("BP") || command.startsWith("BC")){
           try{
               Integer.parseInt(command.substring(2,4));
               return true;
           }catch(NumberFormatException e){
               return false;
           }
       } else{
           return false;
       }
    }
    public static int[] dividePointer(String pointer){
        int[] div = new int[2];
        div[0] = Integer.parseInt(pointer.substring(0,2));
        div[1] = Integer.parseInt(pointer.substring(2,4));
        return div;
    }

    //reikia sutvarkyt kad @command niekada nebutu null
    public static void executeCommand(String command) {
        String tmp;
        Processor.setMODE(0);
        if(command.equals("ADD_")){            
            int[] arg1 = dividePointer(Stack.getSP());
            Stack.decreaseSP();
            int[] arg2 = dividePointer(Stack.getSP());
            int a = Integer.parseInt(Stack.getMemoryFrom(arg1[0], arg1[1]));
            int b = Integer.parseInt(Stack.getMemoryFrom(arg2[0], arg2[1]));
            int c = a + b;
            Stack.setMemoryAt(arg2[0], arg2[1], Integer.toString(c));
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("SUB_")){
            int[] arg1 = dividePointer(Stack.getSP());
            Stack.decreaseSP();
            int[] arg2 = dividePointer(Stack.getSP());
            int a = Integer.parseInt(Stack.getMemoryFrom(arg1[0], arg1[1]));
            int b = Integer.parseInt(Stack.getMemoryFrom(arg2[0], arg2[1]));
            int c = a - b;
            Stack.setMemoryAt(arg2[0], arg2[1], Integer.toString(c));
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("MUL_")){
            int[] arg1 = dividePointer(Stack.getSP());
            Stack.decreaseSP();
            int[] arg2 = dividePointer(Stack.getSP());
            int a = Integer.parseInt(Stack.getMemoryFrom(arg1[0], arg1[1]));
            int b = Integer.parseInt(Stack.getMemoryFrom(arg2[0], arg2[1]));
            int c = a * b;
            Stack.setMemoryAt(arg2[0], arg2[1], Integer.toString(c));
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("DIV_")){
            int[] arg1 = dividePointer(Stack.getSP());
            Stack.decreaseSP();
            int[] arg2 = dividePointer(Stack.getSP());
            int a = Integer.parseInt(Stack.getMemoryFrom(arg1[0], arg1[1]));
            int b = Integer.parseInt(Stack.getMemoryFrom(arg2[0], arg2[1]));
            int div = a / b;
            int mod = a % b;
            Stack.setMemoryAt(arg1[0], arg1[1], Integer.toString(div));
            Stack.setMemoryAt(arg2[0], arg2[1], Integer.toString(mod));
            Stack.increaseSP();
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("CMP_")){
            int[] arg1 = dividePointer(Stack.getSP());
            Stack.decreaseSP();
            int[] arg2 = dividePointer(Stack.getSP());
            int a = Integer.parseInt(Stack.getMemoryFrom(arg1[0], arg1[1]));
            int b = Integer.parseInt(Stack.getMemoryFrom(arg2[0], arg2[1]));
            if(a==b){
                tmp=Processor.replaceCharAt(Processor.getSF(), 0, '1');
                Processor.setSF(tmp);
            }else if(a>b){
                tmp=Processor.replaceCharAt(Processor.getSF(), 1, '1');
                Processor.setSF(tmp);
            }else{
                tmp=Processor.replaceCharAt(Processor.getSF(), 1, '0');
                Processor.setSF(tmp);
            }
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("SCAN")){
            Processor.setMODE(1);
            Processor.setPI(2);
            Processor.setTIMER(Processor.getTIMER()+2);
        }else if(command.equals("PRNT")){
            Processor.setMODE(1);
            Processor.setPI(1);
            Processor.setTIMER(Processor.getTIMER()+2);
        }else if(command.equals("PUSH")){
            if(pushed){                
                Stack.increaseSP();
            }else{          
                pushed=true;
            }
          
            int[] data = dividePointer(VirtualMachine.getIP());
            int[] stack = dividePointer(Stack.getSP());
            String a = (VirtualMachine.getMemoryFrom(data[0], data[1]+1));
            Stack.setMemoryAt(stack[0], stack[1], a);
            if (stack[1] == 15) {
                stack[0]++;
                PagingMechanism.setPagingTableStack(stack[0]);
            }
            VirtualMachine.increaseIP();
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("POP_")){
            Stack.decreaseSP();
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("BRN_")){
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.equals("HALT")){
            Processor.setMODE(1);
            Processor.setPI(3);
            Processor.setTIMER(Processor.getTIMER()+1);
        }else if(command.startsWith("JM")){
            try {
                String x = command.substring(2,3);
                String y = command.substring(3,4);

                int x1 = Processor.hexToDec(x);
                int y1 = Processor.hexToDec(y);
                x = Processor.convertXtoXX(x1);
                y = Processor.convertXtoXX(y1);
                VirtualMachine.setIP(x+y);

                VirtualMachine.decreaseIP();
                Processor.setTIMER(Processor.getTIMER()+1);
                
            } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
            }
        }else if(command.startsWith("JB")){
            try {
                if(Processor.getSF().charAt(1) == '0'){
                    String x = command.substring(2,3);
                    String y = command.substring(3,4);

                    int x1 = Processor.hexToDec(x);
                    int y1 = Processor.hexToDec(y);
                    x = Processor.convertXtoXX(x1);
                    y = Processor.convertXtoXX(y1);
                    VirtualMachine.setIP(x+y);
                    VirtualMachine.decreaseIP();
                    Processor.setTIMER(Processor.getTIMER()+1);
                }
            } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
            }
        }else if(command.startsWith("JE")){
            try {
                if(Processor.getSF().charAt(0) == '1'){
                    String x = command.substring(2,3);
                    String y = command.substring(3,4);
                    int x1 = Processor.hexToDec(x);
                    int y1 = Processor.hexToDec(y);
                    x = Processor.convertXtoXX(x1);
                    y = Processor.convertXtoXX(y1);
                    VirtualMachine.setIP(x+y);
                    VirtualMachine.decreaseIP();
                    Processor.setTIMER(Processor.getTIMER()+1);
                }
            } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
            }
        }else if(command.startsWith("JA")){
            try {
                if(Processor.getSF().charAt(1) == '1'){
                    String x = command.substring(2,3);
                    String y = command.substring(3,4);

                    int x1 = Processor.hexToDec(x);
                    int y1 = Processor.hexToDec(y);
                    x = Processor.convertXtoXX(x1);
                    y = Processor.convertXtoXX(y1);
                    VirtualMachine.setIP(x+y);
                    VirtualMachine.decreaseIP();
                    Processor.setTIMER(Processor.getTIMER()+1);
                }
           } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
           }
        }else if(command.startsWith("BP")){
            try {
                if(Processor.getSF().charAt(3) == '1'){
                    String x = command.substring(2,3);
                    String y = command.substring(3,4);
                    int x1 = Processor.hexToDec(x);
                    int y1 = Processor.hexToDec(y);
                    x = Processor.convertXtoXX(x1);
                    y = Processor.convertXtoXX(y1);
                    VirtualMachine.setIP(x+y);
                    VirtualMachine.decreaseIP();
                    Processor.setTIMER(Processor.getTIMER()+1);
                }
            } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
            }
        }else if(command.startsWith("BC")){
            try {
                if(Processor.getSF().charAt(3) == '0'){
                    String x = command.substring(2,3);
                    String y = command.substring(3,4);
                    int x1 = Processor.hexToDec(x);
                    int y1 = Processor.hexToDec(y);
                    x = Processor.convertXtoXX(x1);
                    y = Processor.convertXtoXX(y1);
                    VirtualMachine.setIP(x+y);
                    VirtualMachine.decreaseIP();
                    Processor.setTIMER(Processor.getTIMER()+1);
                }
            } catch(NumberFormatException e) {
                Processor.setMODE(1);
                Processor.setSI(3);
            }
        }
    }


}
